package com.sh.data.engine.common.annotation.fuzzyQuery;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: jingchen.hr
 * @description:模糊查询特殊字符转义切面
 * @date: 2022/4/23 16:32
 */
@Order(Ordered.HIGHEST_PRECEDENCE)
@Aspect
@Component
@Slf4j
public class FuzzyFieldAop {

    @Pointcut("@annotation(com.sh.data.engine.common.annotation.fuzzyQuery.FuzzyMethod)")
    public void annotationPointCut() {
    }

    @Around("annotationPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object responseObj = null;
        Object[] args = joinPoint.getArgs();
        Object[] clone = Arrays.copyOf(args, args.length);
        try {

            Signature signature = joinPoint.getSignature();
            MethodSignature methodSignature = (MethodSignature) signature;
            Method method = methodSignature.getMethod();
            FuzzyMethod annotation = method.getAnnotation(FuzzyMethod.class);
            int index = annotation.fuzzyParamIndex();
            //get请求 非对象入参数
            if (index != 999 && index < args.length) {
//                System.out.println(args[index]);
                if (Objects.nonNull(args[index])) {
                    args[index] = handleParam(args[index].toString());
                }
            } else {
                //POST请求或GET请求 对象入参
                for (Object arg : args) {
                    if (Objects.nonNull(arg)) {
                        Field[] declaredFields = arg.getClass().getDeclaredFields();
                        for (Field declaredField : declaredFields) {
                            boolean isFuzzyField = declaredField.isAnnotationPresent(FuzzyField.class);
                            if (isFuzzyField) {
                                declaredField.setAccessible(true);
                                if (Objects.nonNull(declaredField.get(arg))) {
                                    String originValue = (String) declaredField.get(arg);
                                    declaredField.set(arg, handleParam(originValue));
                                }

                            }
                        }
                    }
                }
            }

//      HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//      Map<String, String[]> parameterMap = request.getParameterMap();

        } catch (Throwable throwable) {
            log.error(throwable.getMessage(), throwable);
            args = clone;
        } finally {
            //执行
            responseObj = joinPoint.proceed(args);
        }
        return responseObj;
    }


    private String handleParam(String originValue) {
        String varPattern = "\\$|\\(|\\)|\\*|\\+|\\.|\\[|\\]|\\?|\\\\|\\^|\\{|\\|";
        Pattern pattern = Pattern.compile(varPattern);
        //String param = "as\\}asd\\{$";
        Matcher matcher = pattern.matcher(originValue);
        if (!matcher.find()) {
            return originValue;
        }
        //重置matcher
        matcher.reset();

        ArrayList<String> specials = Lists.newArrayList();
        while (matcher.find()) {
            String group = matcher.group();
            specials.add(group);

        }
        for (String special : specials) {
            originValue = originValue.replace(special, "\\" + special);
        }
        //System.out.println(originValue);
        return originValue;
    }
}
